#pragma once

#ifndef _H_ZQDB_CALC_H_
#define _H_ZQDB_CALC_H_

#include <zqdb.h>

#if defined(LIB_CALC_API) && defined(WIN32)
#ifdef LIB_CALC_API_EXPORT
#define CALC_API_EXPORT __declspec(dllexport)
#else
#define CALC_API_EXPORT __declspec(dllimport)
#endif
#else
#define CALC_API_EXPORT 
#endif

#if defined(__cplusplus)
extern "C" {
#endif//

#pragma pack(push, 1)
	
//#define MAX_INDICATOR_INPUT 32
//#define MAX_INDICATOR_REFLINE 16
//#define MAX_INDICATOR_INDEX	16
//
////这里的参数会影响计算结果
//typedef struct tagInputValue
//{
//	char name[MAX_NAME_LENGTH + 1];
//	union
//	{
//		double dvalue;
//		char value[8];
//	};
//	uint64_t number:1;
//	uint64_t digits:4;
//	uint64_t visible:1;
//}INPUTVALUE,*PINPUTVALUE;
//
////REFLINE
//typedef struct tagRefline
//{
//	char name[MAX_NAME_LENGTH + 1];
//	uint32_t type:4;				//ENUM_REFLINE_TYPE
//	uint32_t width:4;			//线宽
//	uint32_t style:4;			//INDICATOR_LINE_STYLE
//	uint32_t digits:4;			//指标精度,如果指定了精度就不使用商品的digits
//	uint32_t color;			//指标颜色
//	double dvalue;			//参考值
//}REFLINE,*PREFLINE;
//
//typedef struct tagIndexInfo
//{
//	char name[MAX_NAME_LENGTH + 1];
//	uint32_t type:4;				//INDICATOR_INDEX_TYPE
//	uint32_t shift:8;			//指标偏移
//	uint32_t begin:8;			//指标开始
//	uint32_t draw:4;				//INDICATOR_DRAW_TYPE
//	uint32_t line:4;				//INDICATOR_LINE_TYPE
//	uint32_t next:4;				//画线关联指标线
//	uint32_t :0;
//	uint32_t digits:4;			//指标精度,如果指定了精度就不使用商品的digits
//	uint32_t width:4;			//线宽
//	uint32_t color;			//指标颜色
//	//double min_value;		//指标最大值
//	//double max_value;		//指标最小值
//	//double base_value;	//基准值
//	//int level_count:8;	//水平线数目
//	//int level_style:24;	//水平线风格
//	//COLORREF level_color;	//水平线颜色
//}INDEXINFO,*PINDEXINFO;
//
//typedef struct tagIndicatorInfo
//{
//		char name[MAX_NAME_LENGTH + 1]; //名称
//		uint32_t type:3;
//		uint32_t style:9; //风格
//		uint32_t shift:7; //指标偏移
//		uint32_t intcount:5; //输入参数数目
//		uint32_t refcount:4; //参考线数目
//		uint32_t idxcount:4; //index个数
//		double refline[MAX_INDICATOR_REFLINE]; //参考线
//		INPUTVALUE input[MAX_INDICATOR_INPUT]; //输入参数
//		INDEXINFO index[MAX_INDICATOR_INDEX]; //index信息
//}INDICATORINFO,*PINDICATORINFO;

//#define STR_ZQDB_FIELD_CALC_SHIFT "SHIFT" //uint8_t 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE_COUNT "REFLINE_COUNT" //uint8_t 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE1 "REFLINE1" //double 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE2 "REFLINE2" //double 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE3 "REFLINE3" //double 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE4 "REFLINE4" //double 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE5 "REFLINE5" //double 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE6 "REFLINE6" //double 类型
//#define STR_ZQDB_FIELD_CALC_REFLINE7 "REFLINE7" //double 类型
#define STR_ZQDB_CALC_RESULT_FIELD_NAME "name" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_TYPE "type" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_DATA_TYPE "data_type" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_DATA_SIZE "data_size" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_SHIFT "shift" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_BEGIN "begin" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_DIGITS "digits" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_DRAW_TYPE "draw_type" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_LINE_TYPE "line_type" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_NEXT "next" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_WIDTH "width" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_DRAW_REF "draw_ref" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_DRAW_DIR "draw_dir" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_DRAW_POS "draw_pos" //uint8_t 类型
#define STR_ZQDB_CALC_RESULT_FIELD_COLOR "color" //uint8_t 类型

/*DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, SHIFT); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE_COUNT); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE1); //double 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE2); //double 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE3); //double 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE4); //double 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE5); //double 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE6); //double 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC, REFLINE7); //double 类型
//
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, TYPE); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, SIZE); //uint32_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, NAME); //string 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, RESULT_TYPE); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, SHIFT); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, BEGIN); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, DIGITS); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, DRAW_TYPE); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, LINE_TYPE); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, NEXT); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, WIDTH); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, DRAW_REF); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, DRAW_DIR); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, DRAW_POS); //uint8_t 类型
DECLARE_MDB_FIELD(CALC_API_EXPORT, CALC, CALC_RESULT, COLOR); //uint8_t 类型*/

/**
* @brief 计算类型
*/
enum CALC_TYPE
{
	CALC_MAJOR,	//主
	CALC_MINOR,	//副
	CALC_DRAWLINE, //划线
	CALC_CONTAINER, //容器
	CALC_FILTER, //过滤
	CALC_SORT, //排序
	CALC_SCRIPT, //脚本
	CALC_STRATEGY //策略
};
#define CALC_TYPE_MAX 8

/**
* @brief 计算语言
*/
enum CALC_LANG_TYPE
{
	CALC_LANG_C_CPP, //C/C++
	CALC_LANG_PYTHON, //PYTHON
	CALC_LANG_MYLANG, //麦语言
};
#define CALC_LANG_TYPE_MAX 3

/**
* @brief 计算目标
*/
enum CALC_TARGET_TYPE
{
	CALC_TARGET_NONE,	//无
	CALC_TARGET_CODE,	//代码
	CALC_TARGET_LIST,	//列表
	CALC_TARGET_CALC,	//算法指定
};
#define CALC_TARGET_TYPE_MAX 4

/**
* @brief 输入参数类型
* 输入参数顺序：VISIBLE,...,HIDE,...
*/
enum CALC_INPUT_FIELD_TYPE
{
	CALC_INPUT_FIELD_VISIBLE,	//默认输入参数显示在技术画面
	CALC_INPUT_FIELD_HIDE,		//输入参数不显示在技术画面
};
#define CALC_INPUT_FIELD_TYPE_MAX 2

/**
* @brief 线类型
*/
enum CALC_RESULT_TYPE
{
	CALC_RESULT_LINE,		//线(绘制)
	CALC_RESULT_CALC,		//辅助计算(不绘制)
	CALC_RESULT_DRAW,		//文字/绘图(绘制)
	CALC_RESULT_DRAWLINE,	//划线(绘制)（暂不支持）
	CALC_RESULT_LINEREF,	//线引用（和线一样绘制）
	CALC_RESULT_CALCREF,	//辅助计算引用(和辅助计算一样不绘制)
};
#define CALC_RESULT_TYPE_MAX 6

/**
* @brief 线LINE和辅助计算CALC结果类型结构
*/
//double

/**
* @brief 结果绘制参考位置
*/
enum CALC_RESULT_DRAW_REF
{
	CALC_RESULT_DRAW_REF_PRICE_OPEN,
	CALC_RESULT_DRAW_REF_PRICE_HIGH,
	CALC_RESULT_DRAW_REF_PRICE_LOW,
	CALC_RESULT_DRAW_REF_PRICE_CLOSE,
};

/**
* @brief 结果绘制方向
*/
enum CALC_RESULT_DRAW_DIR
{
	CALC_RESULT_DRAW_DIR_ABOVE,		//在...之上
	CALC_RESULT_DRAW_DIR_BELOW,		//在...之下
};

/**
* @brief 文字结果类型结构
* 结果值0跳过
*/
typedef struct tagCalcResultText
{
	union 
	{
		struct {
			uint8_t drawref : 4; //文字/图绘制时的参考位置，CALC_RESULT_DRAW_REF
			uint8_t drawdir : 4; //文字/图绘制时的绘制方向，CALC_RESULT_DRAW_DIR
			uint8_t color;
			char text[6];
		};
		char reserved[8];
	};
}CALCRESULTTEXT,*PCALCRESULTTEXT;

/**
* @brief 绘图结果类型结构
* 结果值0跳过
*/
typedef struct tagCalcResultDraw
{
	union
	{
		struct {
			uint8_t drawref : 4; //文字/图绘制时的参考位置，CALC_RESULT_DRAW_REF
			uint8_t drawdir : 4; //文字/图绘制时的绘制方向，CALC_RESULT_DRAW_DIR
			uint8_t color;
			//uint8_t type;
			//uint8_t draw;
			//uint32_t drawex;
		};
		char reserved[8];
	};
}CALCRESULTDRAW,*PCALCRESULTDRAW;

//---------------------------------------------------------------------------
// 图表显示定义
//---------------------------------------------------------------------------

#ifndef CLR_NONE
#define CLR_NONE                0xFFFFFFFFL
#endif//CLR_NONE

/**
* @brief 显示坐标定义
*/
enum CALC_COORD_TYPE
{
	CALC_COORD_NORMAL = 0,		//普通等分坐标
	CALC_COORD_LOG = 0x01,		//对数坐标
	CALC_COORD_MASK1 = 0X0F,
	CALC_COORD_DIFF = 0x10,		//等差坐标(三等分坐标)
	CALC_COORD_SCALE = 0x20,	//等比坐标
	CALC_COORD_PERCENT = 0x40,	//百分比坐标
	CALC_COORD_GOLDEN = 0x80,	//黄金分割
	CALC_COORD_MASK2 = 0X0F,
};

/**
* @brief 指标线绘制方式
*/
enum CALC_RESULT_LINE_DRAW_TYPE
{
	CALC_DRAW_LINE,				//画线
	CALC_DRAW_SECTION,			//线条
	CALC_DRAW_STICK,				//基于基线画柱状线
	CALC_DRAW_HISTOGRAM,			//基于基线画柱状图
	CALC_DRAW_HISTOGRAM2,		//两个指标命令的柱状图
	CALC_DRAW_HISTOGRAM3,		//三个指标命令的柱状图
	CALC_DRAW_HISTOGRAM4,		//四个指标命令的柱状图
	CALC_DRAW_CANDLES,			//以蜡烛台序列展示
	CALC_DRAW_ARROW,				//画箭头
	CALC_DRAW_FILLING,			//两层间的颜色
	CALC_DRAW_ZIGZAG,			//之字设计允许垂直界面
	CALC_DRAW_BARS,				//以字符序列展示

	CALC_DRAW_COLOR_LINE,		//多色线
	CALC_DRAW_COLOR_SECTION,		//多色分段
	CALC_DRAW_COLOR_HISTOGRAM,	//基于基线的多色直方图
	CALC_DRAW_COLOR_HISTOGRAM2,	//两个指标缓冲区的多色直方图
	CALC_DRAW_COLOR_CANDLES,		//多色蜡烛台
	CALC_DRAW_COLOR_ARROW,		//描绘多色箭头
	CALC_DRAW_COLOR_ZIGZAG,		//多色之字形
	CALC_DRAW_COLOR_BARS,		//多色字节
};
#define CALC_RESULT_LINE_DRAW_TYPE_MAX 20

/**
* @brief 指标文字/绘图绘制方式
*/
enum CALC_RESULT_DRAW_DRAW_TYPE
{
	CALC_DRAW_TEXT, //文字
	CALC_DRAW_DRAW, //绘图
};
#define CALC_RESULT_DRAW_DRAW_TYPE_MAX 2

/**
* @brief 指标线线型
*/
enum CALC_LINE_TYPE
{
	CALC_LINE_SOLID,		//实线
	CALC_LINE_DASH,			//折线
	CALC_LINE_DOT,			//虚线
	CALC_LINE_DASHDOT,		//折点线
	CALC_LINE_DASHDOTDOT,	//双折点线
};
#define CALC_LINE_TYPE_MAX 5

/**
* @brief K线显示方式
*/
enum CALC_KLINE_TYPE
{
	CALC_KLINE_K = 0,	//K线
	CALC_KLINE_BAR,		//美国线
	CALC_KLINE_TREND,	//走势线
};
#define CALC_KLINE_TYPE_MAX 3

/**
* @brief 柱状线显示方式
*/
enum CALC_STICK_TYPE
{
	CALC_STICK_LINE = 0,	//柱状线
	CALC_STICK_BAR,			//柱状图
};
#define CALC_STICK_TYPE_MAX 2

/**
* @brief 柱状图显示方式
*/
enum CALC_HISTOGRAM_TYPE
{
	CALC_HISTOGRAM_LINE = 0,//柱状线
	CALC_HISTOGRAM_BAR,		//美国线
	CALC_HISTOGRAM_K,		//K线
};
#define CALC_HISTOGRAM_TYPE_MAX 3

//---------------------------------------------------------------------------
// 画线指标定义
//---------------------------------------------------------------------------

enum CALC_DRAWLINE_TYPE
{
	CALC_DRAWLINE_NONE = 0,	//
	CALC_DRAWLINE_DDLINE,			// 两点直线
	CALC_DRAWLINE_DOTDOT,			// 两点线段
	CALC_DRAWLINE_PLINE,				// 平行线
	CALC_DRAWLINE_PERLINE,			// 百分比线
	CALC_DRAWLINE_RADIALLINE,		// 两点射线
	CALC_DRAWLINE_BARLINE,			// 栅形线
	//UGUNSLINE,			// 上甘氏线
	//DGUNSLINE,			// 下甘氏线
	CALC_DRAWLINE_GUNSLINE,			// 甘氏线
	CALC_DRAWLINE_GOLDLINE,			// 黄金分割线
	CALC_DRAWLINE_BLACKHOLE,			// 神秘黑洞
	CALC_DRAWLINE_ELLIPSEARC,		// 圆弧
	CALC_DRAWLINE_MULTIARC,			// 多圆弧
	CALC_DRAWLINE_GOLDARC,			// 弧度黄金线
	CALC_DRAWLINE_CIRCLE,			// 圆
	CALC_DRAWLINE_MULTIELLIPSE,		// 多圆
	CALC_DRAWLINE_CYCLELINE,			// 周期线
	CALC_DRAWLINE_FABCYCLELINE,		// 费波纳契周期线
	CALC_DRAWLINE_SUZULINE,			// 速阻线
	CALC_DRAWLINE_SINLINE,			// 正弦线
	CALC_DRAWLINE_RECTANGLE,			// 矩形
	CALC_DRAWLINE_TEXT,				// 文字
	CALC_DRAWLINE_UPARROW,			// 上箭头
	CALC_DRAWLINE_DOWNARROW,			// 下箭头
	CALC_DRAWLINE_STOCKBOX,			// 箱体线
	CALC_DRAWLINE_REGRESSLINE,		// 线性回归
	CALC_DRAWLINE_REGRESSZONE,		// 线性回归带
	CALC_DRAWLINE_REGRESSCHANNEL,	// 回归通道
};
#define CALC_DRAWLINE_TYPE_MAX 27

typedef struct tagCalcPoint
{
	double dvalue;		//y值
	uint32_t date;		//x日期
	uint32_t time;		//x时间
	//char lable[32];
}TCALCPOINT, *PCALCPOINT;

typedef struct tagCalcData
{
	HZQDB h;
	PERIODTYPE cycle;
	size_t cycleex;
}CALCDATA, *PCALCDATA;

/**
* @brief 价格类型定义和KDATA保持一致，扩展KDATA价格类型
*/

#define PRICE_OPEN MDB_FIELD_INDEX(ZQDB, KDATA, OPEN) //开盘价格 
#define PRICE_HIGH MDB_FIELD_INDEX(ZQDB, KDATA, HIGH) //最高价格
#define PRICE_LOW MDB_FIELD_INDEX(ZQDB, KDATA, LOW) //最低价格
#define PRICE_CLOSE MDB_FIELD_INDEX(ZQDB, KDATA, CLOSE) //收盘价格
//#define PRICE_MEDIAN (MAX_MDB_FIELD_INDEX - 0) //中间值（高+低）/2
//#define PRICE_TYPICAL (MAX_MDB_FIELD_INDEX - 1) //典型价格（高+低+收盘价）/3
//#define PRICE_WEIGHTED (MAX_MDB_FIELD_INDEX - 2) //平均价格（高+低+收盘价格+开盘价格）/4
//#define PRICE_AVPRICE (MAX_MDB_FIELD_INDEX - 3) //平均价（成交额/成交量）

/**
* @brief 计算触发方式
*/
enum CALC_TRIGGER_TYPE
{
	CALC_TRIGGER_MARKET, //行情变化触发
	CALC_TRIGGER_BAR, //新增K线触发
};

/**
* @brief MA计算方法
*/
enum CALC_MAType
{
	CALC_MAType_SMA,	//简单移动平均 (SMA)：Simple Moving Average = MA(X,N):X的N日简单移动平均,算法(X1+X2+X3+...+Xn)/N,N支持变量
	CALC_MAType_EMA,	//指数移动平均 (EMA)：Exponential MA = EMA(X,N):X的N日指数移动平均.算法:Y=(X*2+Y'*(N-1))/(N+1)
	CALC_MAType_WMA,	//加权移动平均 Weighted Moving Average = WMA(X,N):X的N日加权移动平均.算法:Yn=(1*X1+2*X2+...+n*Xn)/(1+2+...+n)
	CALC_MAType_DEMA,	//双指数移动平均 Double Exponential Moving Average = 
	CALC_MAType_TEMA,	//三重指数移动平均线 Triple Exponential Moving Average =
	CALC_MAType_TRIMA,	//三角型移动平均 Triangular Moving Average =
	CALC_MAType_KAMA,	//考夫曼自适应移动平均线 Kaufman Adaptive Moving Average = 
	CALC_MAType_MAMA,	//MESA 自适应移动平均线 MESA Adaptive Moving Average = 
	CALC_MAType_T3,		//三重指数移动平均线 （T3） Triple Exponential Moving Average (T3) = 
};

enum CALC_STO_PRICE
{
	CALC_STO_LOWHIGH,	//基于最低价/最高价的计算
	CALC_STO_OPENCLOSE,	//基于开盘价/收盘价的计算
};

/**
* @brief 最大值最小值定义
* CalculatorEx指标的MMX数量和结果/Line数量一致
* K有开高低收4个MMX,分别是开高低收，对应Line是0,1,2,3
* AMOUNT有一个MMX
* VOLUME有一个MMX
* K/AMOUNT/VOLUME是特殊的CalculatorEx
* 综上所述，也就是每一条Line都有对应的MIN,MAX
*/
enum CALC_MMX_TYPE
{
	CALC_MMX_MIN = 0,
	CALC_MMX_MAX,
};
#define CALC_MMX_TYPE_MAX 2

////策略表信息
//typedef struct tagStrategyInfo
//{
//	char name[MAX_NAME_LENGTH + 1]; //名称
//}STRATEGYINFO,*PSTRATEGYINFO;

//API

CALC_API_EXPORT const char* ZQDBGetSrcDir();

typedef void(*ZQDB_CALC_INIT_FN)(HZQDB h, void* userdata);
typedef void(*ZQDB_CALC_TERM_FN)(HZQDB h, void* userdata);
typedef void(*ZQDB_CALC_TIMER_FN)(HZQDB h, void* userdata);
//typedef void(*ZQDB_CALC_NOTIFY_FN)(HZQDB h, HZQDB data, ZQDB_NOTIFY_TYPE type, void* userdata);
typedef struct tagCalcFilterParam
{
	HZQDB code;
	int result;
}CALCFILTERPARAM, *PCALCFILTERPARAM;
typedef struct tagCalcSortParam
{
	HZQDB x;
	HZQDB y;
	bool result;
}CALCSORTPARAM, *PCALCSORTPARAM;
typedef struct tagCalcResult
{
	int data_count;
	int data_counted;
	int result_count;
	void** result_data;
}CALCRESULT, *PCALCRESULT;
typedef void(*ZQDB_CALC_HANDLE_FN)(HZQDB h, HZQDB data, ZQDB_NOTIFY_TYPE type, void* param, void* userdata);

CALC_API_EXPORT void ZQDBCalcRef(HZQDB h);

CALC_API_EXPORT const char* ZQDBCalcType2Str(CALC_TYPE type);

CALC_API_EXPORT MDB_STATUS ZQDBCloseCalcFunc(HZQDB h);
CALC_API_EXPORT HZQDB ZQDBCreateCalcFunc(const char* name, CALC_TYPE type, CALC_LANG_TYPE lang, const char* xml, size_t xmlflag
	, void* userdata, ZQDB_CALC_INIT_FN init_cb, ZQDB_CALC_TERM_FN term_cb
	, ZQDB_CALC_TIMER_FN timer_cb, ZQDB_CALC_HANDLE_FN handle_cb);
CALC_API_EXPORT HZQDB ZQDBOpenCalcFunc(const char* name);
CALC_API_EXPORT HZQDB ZQDBOpenCalcFuncEx(const char* name, CALC_TYPE type);
CALC_API_EXPORT MDB_STATUS ZQDBDeleteCalcFunc(const char* name, CALC_TYPE type, CALC_LANG_TYPE lang);

CALC_API_EXPORT const char* ZQDBGetCalcName(HZQDB h);
CALC_API_EXPORT CALC_TYPE ZQDBGetCalcType(HZQDB h);
CALC_API_EXPORT CALC_LANG_TYPE ZQDBGetCalcLang(HZQDB h);
CALC_API_EXPORT CALC_TARGET_TYPE ZQDBGetCalcTarget(HZQDB h);

CALC_API_EXPORT bool ZQDBIsCalcAuth(HZQDB h);
CALC_API_EXPORT bool ZQDBIsCalcAuthorized(HZQDB h);

CALC_API_EXPORT const char* ZQDBGetDrawlineName(size_t type);
CALC_API_EXPORT CALC_DRAWLINE_TYPE ZQDBGetDrawlineType(const char* name);

CALC_API_EXPORT bool ZQDBCalcIsSubscribe(HZQDB h, size_t flags = 0);
CALC_API_EXPORT void ZQDBCalcSubscribe(HZQDB h);
CALC_API_EXPORT void ZQDBCalcUnSubscribe(HZQDB h);

//CALC_TYPE_MAX返回所有
CALC_API_EXPORT size_t ZQDBGetAllCalcFuncCount(CALC_TYPE type);
CALC_API_EXPORT size_t ZQDBGetAllCalcFunc(CALC_TYPE type, HZQDB* h, size_t count);

#define CALC_DATA_FLAG_SUB_DATA 0X0001 //订阅数据
#define CALC_DATA_FLAG_SYNC_DATA 0X0002 //同步数据
#define CALC_DATA_FLAG_ASYNC_DATA 0X0004 //异步同步数据
#define CALC_DATA_FLAG_TEST_DATA 0X0008 //测试标志

CALC_API_EXPORT MDB_STATUS ZQDBCloseCalcData(HZQDB data);
CALC_API_EXPORT HZQDB ZQDBOpenCalcData(HZQDB code, PERIODTYPE cycle, size_t cycleex, size_t flags);

//获取打开的所有CalcData
CALC_API_EXPORT size_t ZQDBGetAllCalcDataCount(HZQDB calc);
CALC_API_EXPORT size_t ZQDBGetAllCalcData(HZQDB calc, HZQDB* h, size_t count);

CALC_API_EXPORT MDB_STATUS ZQDBCloseCalcInput(HZQDB h);
CALC_API_EXPORT HZQDB ZQDBOpenCalcInput(const char* xml, size_t xmlflag);
CALC_API_EXPORT HZQDB ZQDBCloneCalcInput(HZQDB h);

#define CALCULATOR_FLAG_AUTO_SUB_DATA 0X0001 //引用数据时自动订阅数据
#define CALCULATOR_FLAG_AUTO_SYNC_DATA 0X0002 //引用数据时自动同步数据
#define CALCULATOR_FLAG_AUTO_ASYNC_DATA 0X0004 //引用数据时自动异步同步数据
#define CALCULATOR_FLAG_AUTO_TEST_DATA 0X0008 //测试标志

CALC_API_EXPORT MDB_STATUS ZQDBCloseCalculator(HZQDB calc);
CALC_API_EXPORT HZQDB ZQDBOpenCalculator(const char* name, HZQDB data, PERIODTYPE cycle, size_t cycleex, HZQDB input, HZQDB user, size_t flags);
CALC_API_EXPORT HZQDB ZQDBOpenCalculatorEx(const char* name, CALC_TYPE type, HZQDB data, PERIODTYPE cycle, size_t cycleex, HZQDB input, HZQDB user, size_t flags);

//快速回放/快速回测
CALC_API_EXPORT void ZQDBCalcStartTest();
CALC_API_EXPORT void ZQDBCalcStopTest();
CALC_API_EXPORT bool ZQDBCalcIsTesting();

//手动触发计算一次
CALC_API_EXPORT void ZQDBCalculatorCalc(HZQDB calc);

CALC_API_EXPORT HZQDB ZQDBCalculator();
CALC_API_EXPORT HZQDB ZQDBCalculatorData(HZQDB calc);

CALC_API_EXPORT void ZQDBCalculatorSub(HZQDB calc, HZQDB code);

CALC_API_EXPORT PERIODTYPE ZQDBCalculatorCycle(HZQDB h);
CALC_API_EXPORT size_t ZQDBCalculatorCycleEx(HZQDB h);

CALC_API_EXPORT void ZQDBSetCalcTradeFlag(size_t flag);
CALC_API_EXPORT size_t ZQDBGetCalcTradeFlag();

CALC_API_EXPORT void ZQDBSetDefaultTradeVolume(double volume);
CALC_API_EXPORT void ZQDBSetDefaultTradeAmount(double amount);
CALC_API_EXPORT bool ZQDBIsDefaultTradeByVolume();
CALC_API_EXPORT double ZQDBGetDefaultTradeValue();
//margin_ratio:保证金比例小于等于1，对于股票就是1，期货不同品种不同用户的保证金比例都可能不一样，比如IC0保证金比例是0.2，表示5倍杠杆
CALC_API_EXPORT double ZQDBCalcDefaultTradeVolume(HZQDB hcode, double margin_ratio);

//容器/筛选
//添加结果
CALC_API_EXPORT void ZQDBCalcContainerClearResult(HZQDB calc);
CALC_API_EXPORT void ZQDBCalcContainerAddResult(HZQDB calc, HZQDB h, double weight);
CALC_API_EXPORT void ZQDBCalcContainerRemoveResult(HZQDB calc, HZQDB h);
//获取结果
CALC_API_EXPORT size_t ZQDBCalcContainerFindResult(HZQDB calc, HZQDB h);
CALC_API_EXPORT size_t ZQDBCalcContainerGetResultCount(HZQDB calc);
CALC_API_EXPORT size_t ZQDBCalcContainerGetResult(HZQDB calc, HZQDB* h, size_t count);
CALC_API_EXPORT HZQDB ZQDBCalcContainerGetResultByPos(HZQDB calc, size_t pos);
//手动筛选一个代码
CALC_API_EXPORT int ZQDBCalcFilterCalc(HZQDB calc, HZQDB code);

//排序
CALC_API_EXPORT bool ZQDBCalcSortIsDynamic(HZQDB calc);
CALC_API_EXPORT bool ZQDBCalcCmp(HZQDB calc, HZQDB x, HZQDB y);
CALC_API_EXPORT void ZQDBCalcSort(HZQDB calc, HZQDB* h, size_t count);

CALC_API_EXPORT void ZQDBSetCalculatorData(HZQDB calc, void* data);
CALC_API_EXPORT void* ZQDBGetCalculatorData(HZQDB calc);

//获取打开的所有Calculator
CALC_API_EXPORT size_t ZQDBGetAllCalculatorCount(HZQDB calc);
CALC_API_EXPORT size_t ZQDBGetAllCalculator(HZQDB calc, HZQDB* h, size_t count);

//获取打开的所有Strategy
CALC_API_EXPORT size_t ZQDBGetAllStrategyCount();
CALC_API_EXPORT size_t ZQDBGetAllStrategy(HZQDB* h, size_t count);

//启停策略（默认创建策略是不运行的，必须主动启动策略，关闭也不会主动停止策略，必须主动停止策略）
CALC_API_EXPORT bool ZQDBCalcStrategyIsRun(HZQDB calc);
CALC_API_EXPORT MDB_STATUS ZQDBCalcStrategyStart(HZQDB calc);
CALC_API_EXPORT MDB_STATUS ZQDBCalcStrategyStop(HZQDB calc);

CALC_API_EXPORT bool ZQDBHasCalcAttr(HZQDB h, const char* field);
CALC_API_EXPORT ssize_t ZQDBGetCalcAttrAsInt(HZQDB h, const char* field, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcAttrAsDouble(HZQDB h, const char* field, double def);
CALC_API_EXPORT char* ZQDBGetCalcAttrAsStr(HZQDB h, const char* field, char* val, size_t valen);
CALC_API_EXPORT char* ZQDBGetCalcAttrAsStrEx(HZQDB h, const char* field, char* val, size_t valen);

CALC_API_EXPORT size_t ZQDBGetCalcInputAttrCount(HZQDB h, CALC_INPUT_FIELD_TYPE type);
CALC_API_EXPORT void ZQDBSetCalcInputAttrAsInt(HZQDB h, const char* field, ssize_t val);
CALC_API_EXPORT void ZQDBSetCalcInputAttrAsDouble(HZQDB h, const char* field, double val);
CALC_API_EXPORT void ZQDBSetCalcInputAttrAsStr(HZQDB h, const char* field, const char* val);
CALC_API_EXPORT ssize_t ZQDBGetCalcInputAttrAsInt(HZQDB h, const char* field, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcInputAttrAsDouble(HZQDB h, const char* field, double def);
CALC_API_EXPORT char* ZQDBGetCalcInputAttrAsStr(HZQDB h, const char* field, char* val, size_t valen);
CALC_API_EXPORT const char* ZQDBGetCalcInputAttrNameEx(HZQDB h, size_t index);
CALC_API_EXPORT const char* ZQDBGetCalcInputAttrValueEx(HZQDB h, size_t index);
CALC_API_EXPORT ssize_t ZQDBGetCalcInputAttrAsIntEx(HZQDB h, size_t index, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcInputAttrAsDoubleEx(HZQDB h, size_t index, double def);
CALC_API_EXPORT char* ZQDBGetCalcInputAttrAsStrEx(HZQDB h, size_t index, char* val, size_t valen);

CALC_API_EXPORT size_t ZQDBGetCalcReflineAttrCount(HZQDB h);
CALC_API_EXPORT ssize_t ZQDBGetCalcReflineAttrAsInt(HZQDB h, size_t index, const char* field, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcReflineAttrAsDouble(HZQDB h, size_t index, const char* field, double def);
CALC_API_EXPORT char* ZQDBGetCalcReflineAttrAsStr(HZQDB h, size_t index, const char* field, char* val, size_t valen);

//CALC_API_EXPORT size_t ZQDBGetCalcResultCount(HZQDB h);
CALC_API_EXPORT size_t ZQDBGetCalcResultAttrCount(HZQDB h);
CALC_API_EXPORT ssize_t ZQDBGetCalcResultAttrAsInt(HZQDB h, size_t index, const char* field, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcResultAttrAsDouble(HZQDB h, size_t index, const char* field, double def);
CALC_API_EXPORT char* ZQDBGetCalcResultAttrAsStr(HZQDB h, size_t index, const char* field, char* val, size_t valen);

CALC_API_EXPORT void ZQDBCalcTimer(); //一秒调用一次
CALC_API_EXPORT size_t ZQDBCalcGetTimer(HZQDB h);
CALC_API_EXPORT void ZQDBCalcSetTimer(HZQDB h, size_t interval);

CALC_API_EXPORT size_t ZQDBCalcIsUpdate(HZQDB h);
CALC_API_EXPORT void ZQDBCalcUpdate(HZQDB h, ZQDB_NOTIFY_TYPE notify);

//CALC_API_EXPORT size_t ZQDBGetCalcAnyDisabledExchange();
//CALC_API_EXPORT size_t ZQDBGetCalcAnyDisabledModule();
CALC_API_EXPORT size_t ZQDBGetCalcAnyDisabledUser();
CALC_API_EXPORT size_t ZQDBGetCalcUserCount();
CALC_API_EXPORT HZQDB ZQDBGetCalcUser(size_t pos);
CALC_API_EXPORT HZQDB ZQDBCalcFindUser(const char* user, const char* broker);

CALC_API_EXPORT size_t ZQDBGetCalcCodeCount(HZQDB calc);
CALC_API_EXPORT size_t ZQDBGetCalcCode(HZQDB calc, HZQDB* h, size_t count);
CALC_API_EXPORT HZQDB ZQDBGetCalcCodeByPos(HZQDB calc, size_t pos);

CALC_API_EXPORT void ZQDBSetCalcData(HZQDB calc, HZQDB h, PERIODTYPE cycle, size_t cycleex);
CALC_API_EXPORT HZQDB ZQDBGetCalcDataCode(HZQDB h);
CALC_API_EXPORT PERIODTYPE ZQDBGetCalcDataCycle(HZQDB h);
CALC_API_EXPORT size_t ZQDBGetCalcDataCycleEx(HZQDB h);
CALC_API_EXPORT ssize_t ZQDBGetCalcDataFieldAsInt(HZQDB h, MDB_FIELD& field, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcDataFieldAsDouble(HZQDB h, MDB_FIELD& field, double def);
CALC_API_EXPORT char* ZQDBGetCalcDataFieldAsStr(HZQDB h, MDB_FIELD& field, char* val, size_t vallen, const char* format);

CALC_API_EXPORT size_t ZQDBGetCalcDataMaxCount(HZQDB data);
CALC_API_EXPORT size_t ZQDBGetCalcDataCount(HZQDB data);
CALC_API_EXPORT void* ZQDBGetCalcData(HZQDB data, MDB_FIELD* field);
CALC_API_EXPORT void* ZQDBGetCalcDataEx(HZQDB data, MDB_FIELD* field, size_t pos);
CALC_API_EXPORT ssize_t ZQDBGetCalcDataAsInt(HZQDB data, MDB_FIELD* field, size_t pos, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcDataAsDouble(HZQDB data, MDB_FIELD* field, size_t pos, double def);
CALC_API_EXPORT char* ZQDBGetCalcDataAsStr(HZQDB data, MDB_FIELD* field, size_t pos, char* val, size_t vallen, const char* format);

//CALC_API_EXPORT double* ZQDBGetCalcDataPrice(HZQDB h, PRICE_TYPE type, size_t pos);

CALC_API_EXPORT MDB_STATUS ZQDBGetCalcDataPosByTime(HZQDB data, uint32_t date, uint32_t time, size_t *pos);
CALC_API_EXPORT MDB_STATUS ZQDBGetCalcDataTimeByPos(HZQDB data, size_t pos, uint32_t *date, uint32_t *time);

CALC_API_EXPORT void ZQDBSetCalcResultValueRef(HZQDB calc, size_t index, HZQDB ref_indicator, size_t ref_index);

CALC_API_EXPORT size_t ZQDBGetCalcResultValueMaxCount(HZQDB calc);
CALC_API_EXPORT size_t ZQDBGetCalcResultValueCount(HZQDB calc);
CALC_API_EXPORT void* ZQDBGetCalcResultValue(HZQDB calc, size_t index, MDB_FIELD* field);
CALC_API_EXPORT void* ZQDBGetCalcResultValueEx(HZQDB calc, size_t index, size_t pos, MDB_FIELD* field);
CALC_API_EXPORT ssize_t ZQDBGetCalcResultValueAsInt(HZQDB h, size_t index, size_t pos, ssize_t def);
CALC_API_EXPORT double ZQDBGetCalcResultValueAsDouble(HZQDB h, size_t index, size_t pos, double def);
CALC_API_EXPORT char* ZQDBGetCalcResultValueAsStr(HZQDB h, size_t index, size_t pos, char* val, size_t vallen, const char* format);
CALC_API_EXPORT void ZQDBSetCalcResultValueAsInt(HZQDB h, size_t index, size_t pos, ssize_t val);
CALC_API_EXPORT void ZQDBSetCalcResultValueAsDouble(HZQDB h, size_t index, size_t pos, double val);
CALC_API_EXPORT void ZQDBSetCalcResultValueAsStr(HZQDB h, size_t index, size_t pos, const char* val, size_t vallen);

CALC_API_EXPORT HZQDB ZQDBCalcGetUser(HZQDB calc);
CALC_API_EXPORT HZQDB ZQDBCalcSetUser(HZQDB user);

CALC_API_EXPORT int ZQDBCalcOrderSend(HZQDB code, char direction, char offset, char type, double volume, double price, HNMSG* rsp, size_t timeout);
CALC_API_EXPORT int ZQDBCalcOrderCancel(HZQDB order, HNMSG* rsp, size_t timeout);
CALC_API_EXPORT int ZQDBCalcOrderClose(HZQDB position, char type, double volume, double price, HNMSG* rsp, size_t timeout);

//返回所有CalcModule
CALC_API_EXPORT size_t ZQDBGetAllCalcModuleCount();
CALC_API_EXPORT size_t ZQDBGetAllCalcModule(HZQDB* h, size_t count);

CALC_API_EXPORT CALC_LANG_TYPE ZQDBCalcModuleGetLang(HZQDB h);

//CALC_API_EXPORT int ZQDBCalcModuleGetFuncCount(HZQDB h);
//CALC_API_EXPORT int ZQDBCalcModuleGetFunc(HZQDB h, size_t pos, char* name, int* namelen);

CALC_API_EXPORT bool ZQDBCalcModuleExistFunc(HZQDB h, CALC_TYPE type, const char* name);

CALC_API_EXPORT int ZQDBCalcModuleNewFunc(HZQDB h, CALC_TYPE type, const char* name, void(*cb)(const char* src, void* data), void* data);
CALC_API_EXPORT int ZQDBCalcModuleLoadFunc(HZQDB h, CALC_TYPE type, const char* name, void(*cb)(const char* src, void* data), void* data);
CALC_API_EXPORT int ZQDBCalcModuleSaveFunc(HZQDB h, CALC_TYPE type, const char* name, const char* src);
CALC_API_EXPORT int ZQDBCalcModuleDeleteFunc(HZQDB h, CALC_TYPE type, const char* name);
CALC_API_EXPORT int ZQDBCalcModuleRenameFunc(HZQDB h, CALC_TYPE type, const char* from, const char* to);

CALC_API_EXPORT int ZQDBCalcModuleCompileFunc(HZQDB h, CALC_TYPE type, const char* name, const char* src, void(*cb)(const char* err, void* data), void* data);
CALC_API_EXPORT int ZQDBCalcModuleApplyFunc(HZQDB h, CALC_TYPE type, const char* name, const char* src);

//系统指标函数

/*
* ZQDBCalc_MAX - Max
*
* Input  = double
* Output = double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 2 to 100000)
*    Number of period
*
*
*/
CALC_API_EXPORT int ZQDBCalc_MAX(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
* ZQDBCalc_MIN - Min
*
* Input  = double
* Output = double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 2 to 100000)
*    Number of period
*
*
*/
CALC_API_EXPORT int ZQDBCalc_MIN(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
* ZQDBCalc_SUM - Sum
*
* Input  = double
* Output = double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 2 to 100000)
*    Number of period
*
*
*/
CALC_API_EXPORT int ZQDBCalc_SUM(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
* ZQDBCalc_MA - Moving average
*
* Input  = double
* Output = double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 1 to 100000)
*    Number of period
*
* optInMAType:
*    Type of Moving Average
*
*
*/
CALC_API_EXPORT int ZQDBCalc_MA(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 1 to 100000 */
	CALC_MAType     optInMAType,
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
* ZQDBCalc_SMA - Smoothing moving average
*
* Input  = double
* Output = double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 1 to 100000)
*    Number of period
*
* optInWeight:(From 1 to optInTimePeriod)
*    Number of weight
*
*/
CALC_API_EXPORT int ZQDBCalc_SMA(int    start,
	int    end,
	const double inReal[],
	int		optInTimePeriod, /* From 1 to 100000 */
	int		optInWeight, /* From 1 to optInTimePeriod */
	int		offset, /*Out buffer offset*/
	double	outReal[]);

/*
* ZQDBCalc_DMA - Dynamic moving average
*
* Input  = double,double
* Output = double
*
*/
CALC_API_EXPORT int ZQDBCalc_DMA(int    start,
	int    end,
	const double inReal[],
	const double inA[],/*A必须大于0且小于1*/
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
* ZQDBCalc_MACD - Moving Average Convergence/Divergence
*
* Input  = double
* Output = double, double, double
*
* Optional Parameters
* -------------------
* optInFastPeriod:(From 2 to 100000)
*    Number of period for the fast MA
*
* optInSlowPeriod:(From 2 to 100000)
*    Number of period for the slow MA
*
* optInSignalPeriod:(From 1 to 100000)
*    Smoothing for the signal line (nb of period)
*
*
*/
CALC_API_EXPORT int ZQDBCalc_MACD(int    start,
	int    end,
	const double inReal[],
	int           optInFastPeriod, /* From 2 to 100000 */
	int           optInSlowPeriod, /* From 2 to 100000 */
	int           optInSignalPeriod, /* From 1 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outDIF[],
	double        outDEA[],
	double        outMACD[],
	double        outFast[],
	double        outSlow[]);

/*
 * ZQDBCalc_DEV - Deviation
 * 
 * Input  = double
 * Output = double
 * 
 * Optional Parameters
 * -------------------
 * optInTimePeriod:(From 2 to 100000)
 *    Number of period
 *
 * 
 */
CALC_API_EXPORT int ZQDBCalc_DEV(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
* ZQDBCalc_AVEDEV - Average abs deviation
*
* Input  = double
* Output = double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 2 to 100000)
*    Number of period
*
*
*/
CALC_API_EXPORT int ZQDBCalc_AVEDEV(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outAVE[],
	double        outDEV[]);

/*
 * ZQDBCalc_VAR - Variance
 * 
 * Input  = double
 * Output = double
 * 
 * Optional Parameters
 * -------------------
 * optInTimePeriod:(From 1 to 100000)
 *    Number of period
 * 
 * 
 */
CALC_API_EXPORT int ZQDBCalc_VAR(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 1 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
 * ZQDBCalc_STDDEV - Standard Deviation
 * 
 * Input  = double
 * Output = double
 * 
 * Optional Parameters
 * -------------------
 * optInTimePeriod:(From 2 to 100000)
 *    Number of period
 * 
 * 
 */
CALC_API_EXPORT int ZQDBCalc_STDDEV(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

/*
* ZQDBCalc_BBANDS - Bollinger Bands
*
* Input  = double
* Output = double, double, double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 2 to 100000)
*    Number of period
*
* optInNbDevUp:(From TA_REAL_MIN to TA_REAL_MAX)
*    Deviation multiplier for upper band
*
* optInNbDevDn:(From TA_REAL_MIN to TA_REAL_MAX)
*    Deviation multiplier for lower band
*
* optInMAType:
*    Type of Moving Average
*
*
*/
CALC_API_EXPORT int ZQDBCalc_BBANDS(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	double        optInNbDevUp, /* From TA_REAL_MIN to TA_REAL_MAX */
	double        optInNbDevDn, /* From TA_REAL_MIN to TA_REAL_MAX */
	CALC_MAType     optInMAType,
	int			  offset, /*Out buffer offset*/
	double        outRealUpperBand[],
	double        outRealMiddleBand[],
	double        outRealLowerBand[]);

/*
* ZQDBCalc_STOCH - Stochastic
*
* Input  = High, Low, Close
* Output = double, double
*
* Optional Parameters
* -------------------
* optInFastK_Period:(From 1 to 100000)
*    Time period for building the Fast-K line
*
* optInSlowK_Period:(From 1 to 100000)
*    Smoothing for making the Slow-K line. Usually set to 3
*
* optInSlowK_MAType:
*    Type of Moving Average for Slow-K
*
* optInSlowD_Period:(From 1 to 100000)
*    Smoothing for making the Slow-D line
*
* optInSlowD_MAType:
*    Type of Moving Average for Slow-D
*
*
*/
CALC_API_EXPORT int ZQDBCalc_STOCH(int    startIdx,
	int    endIdx,
	const double inHigh[],
	const double inLow[],
	const double inClose[],
	int           optInFastK_Period, /* From 1 to 100000 */
	int           optInSlowK_Period, /* From 1 to 100000 */
	CALC_MAType     optInSlowK_MAType,
	int           optInSlowD_Period, /* From 1 to 100000 */
	CALC_MAType     optInSlowD_MAType,
	int			  offset, /*Out buffer offset*/
	double        outSlowK[],
	double        outSlowD[]);
CALC_API_EXPORT int ZQDBCalc_KDJ(int    start,
	int    end,
	const double inHigh[],
	const double inLow[],
	const double inClose[],
	int           optInFastK_Period, /* From 1 to 100000 */
	int           optInFastD_Period, /* From 1 to 100000 */
	int           optInSlowD_Period, /* From 1 to 100000 */
	CALC_MAType     optInMAType,
	int			  offset, /*Out buffer offset*/
	double        outFastK[],
	double        outFastD[],
	double        outFastJ[]);

/*
* ZQDBCalc_STOCHF - Stochastic Fast
*
* Input  = High, Low, Close
* Output = double, double
*
* Optional Parameters
* -------------------
* optInFastK_Period:(From 1 to 100000)
*    Time period for building the Fast-K line
*
* optInFastD_Period:(From 1 to 100000)
*    Smoothing for making the Fast-D line. Usually set to 3
*
* optInFastD_MAType:
*    Type of Moving Average for Fast-D
*
*
*/
CALC_API_EXPORT int ZQDBCalc_STOCHF(int    start,
	int    end,
	const double inHigh[],
	const double inLow[],
	const double inClose[],
	int           optInFastK_Period, /* From 1 to 100000 */
	int           optInFastD_Period, /* From 1 to 100000 */
	CALC_MAType     optInFastD_MAType,
	int			  offset, /*Out buffer offset*/
	double        outFastK[],
	double        outFastD[]);

/*
* ZQDBCalc_STOCHRSI - Stochastic Relative Strength Index
*
* Input  = double
* Output = double, double
*
* Optional Parameters
* -------------------
* optInTimePeriod:(From 2 to 100000)
*    Number of period
*
* optInFastK_Period:(From 1 to 100000)
*    Time period for building the Fast-K line
*
* optInFastD_Period:(From 1 to 100000)
*    Smoothing for making the Fast-D line. Usually set to 3
*
* optInFastD_MAType:
*    Type of Moving Average for Fast-D
*
*
*/
CALC_API_EXPORT int ZQDBCalc_STOCHRSI(int    start,
	int    end,
	const double inReal[],
	int           optInTimePeriod, /* From 2 to 100000 */
	int           optInFastK_Period, /* From 1 to 100000 */
	int           optInFastD_Period, /* From 1 to 100000 */
	CALC_MAType     optInFastD_MAType,
	int			  offset, /*Out buffer offset*/
	double        outFastK[],
	double        outFastD[]);

/*
* ZQDBCalc_RSV - Raw Stochastic Value
*
* Input  = High, Low, Close
* Output = double, double
*
* Optional Parameters
* -------------------
* optInFastK_Period:(From 1 to 100000)
*    Time period for building the Fast-K line
*
* optInFastD_Period:(From 1 to 100000)
*    Smoothing for making the Fast-D line. Usually set to 3
*
* optInFastD_MAType:
*    Type of Moving Average for Fast-D
*
*
*/
CALC_API_EXPORT int ZQDBCalc_RSV(int    start,
	int    end,
	const double inHigh[],
	const double inLow[],
	const double inClose[],
	int           optInTimePeriod, /* From 1 to 100000 */
	int			  offset, /*Out buffer offset*/
	double        outReal[]);

#pragma pack(pop)

#if defined(__cplusplus)
}

#include <cassert>
#include <string>
#include <vector>

namespace zqdb { 

	namespace Calc {

class InputAttr
{
protected:
	HZQDB h_ = nullptr;
	bool auto_close_ = true;
public:
	InputAttr() {}
	InputAttr(const char* xml, size_t xmlflag) :h_(ZQDBOpenCalcInput(xml, xmlflag))
	{

	}
	/*InputAttr(HZQDB h) :h_(ZQDBCloneCalcInput(h))
	{

	}*/
	InputAttr(HZQDB h, bool ref = false) :h_(h), auto_close_(ref) {
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	InputAttr(const InputAttr& o)
	{
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	InputAttr& operator=(const InputAttr& o) {
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
		return *this;
	}
	InputAttr(InputAttr&& o)
	{
		h_ = o.h_;
		o.h_ = nullptr;
		auto_close_ = o.auto_close_;
		o.auto_close_ = false;
	}
	InputAttr& operator=(InputAttr&& o)
	{
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_;
		o.h_ = nullptr;
		auto_close_ = o.auto_close_;
		o.auto_close_ = false;
		return *this;
	}
	~InputAttr()
	{
		Close();
	}

	inline void Close() {
		if (h_ && auto_close_) {
			ZQDBCloseCalcInput(h_);
			h_ = nullptr;
		}
	}

	inline operator HZQDB() const { return h_; }

	size_t GetAttrCount(HZQDB h, CALC_INPUT_FIELD_TYPE type = CALC_INPUT_FIELD_VISIBLE) { return ZQDBGetCalcInputAttrCount(h_, type); }
	void SetAttrAsInt(const char* field, ssize_t val) { ZQDBSetCalcInputAttrAsInt(h_, field, val); }
	void SetAttrAsDouble(const char* field, double val) { ZQDBSetCalcInputAttrAsDouble(h_, field, val); }
	void SetAttrAsStr(const char* field, const char* val) { ZQDBSetCalcInputAttrAsStr(h_, field, val); }
	ssize_t GetAttrAsInt(const char* field, ssize_t def = 0) { return ZQDBGetCalcInputAttrAsInt(h_, field, def); }
	double GetAttrAsDouble(const char* field, double def = 0.) { return ZQDBGetCalcInputAttrAsDouble(h_, field, def); }
	char* GetAttrAsStr(const char* field, char* val, size_t valen) { return ZQDBGetCalcInputAttrAsStr(h_, field, val, valen); }
	const char* GetAttrName(size_t index) { return ZQDBGetCalcInputAttrNameEx(h_, index); }
	const char* GetAttrValue(size_t index) { return ZQDBGetCalcInputAttrValueEx(h_, index); }
	ssize_t GetAttrAsInt(size_t index, ssize_t def = 0) { return ZQDBGetCalcInputAttrAsIntEx(h_, index, def); }
	double GetAttrAsDouble(size_t index, double def = 0.) { return ZQDBGetCalcInputAttrAsDoubleEx(h_, index, def); }
	char* GetAttrAsStr(size_t index, char* val, size_t valen) { return ZQDBGetCalcInputAttrAsStrEx(h_, index, val, valen); }
};

class AllModule : public std::vector<HZQDB> {
public:
	AllModule() {
		std::vector<HZQDB>& vec = *this;
		auto vec_count = ZQDBGetAllCalcModuleCount();
		if (vec_count > 0) {
			vec.resize(vec_count);
			vec.resize(ZQDBGetAllCalcModule(&vec[0], vec.size()));
		}
	}
};

class AllFunc : public std::vector<HZQDB> {
protected:
	CALC_TYPE type_;
public:
	AllFunc(CALC_TYPE type):type_(type) {
		Update();
	}
	~AllFunc()
	{
		std::vector<HZQDB>& hfuncs = *this;
		for (auto h : hfuncs) {
			ZQDBCloseCalcFunc(h);
		}
	}
	void Update()
	{
		std::vector<HZQDB>& hfuncs = *this;
		for (auto h : hfuncs) {
			ZQDBCloseCalcFunc(h);
		}
		//
		auto func_count = ZQDBGetAllCalcFuncCount(type_);
		if (func_count > 0) {
			hfuncs.resize(func_count);
			hfuncs.resize(ZQDBGetAllCalcFunc(type_, &hfuncs[0], hfuncs.size()));
		}
	}
};

class AllCalcData : public std::vector<HZQDB> {
public:
	AllCalcData(HZQDB h) {
		std::vector<HZQDB>& hdatas = *this;
		auto count = ZQDBGetAllCalcDataCount(h);
		if (count > 0) {
			hdatas.resize(count);
			hdatas.resize(ZQDBGetAllCalcData(h, &hdatas[0], hdatas.size()));
		}
	}
	~AllCalcData()
	{
		std::vector<HZQDB>& hdatas = *this;
		for (auto h : hdatas) {
			ZQDBCloseCalcData(h);
		}
	}
};

class AllCalculator : public std::vector<HZQDB> {
public:
	AllCalculator(HZQDB h) {
		std::vector<HZQDB>& hdatas = *this;
		auto count = ZQDBGetAllCalculatorCount(h);
		if (count > 0) {
			hdatas.resize(count);
			hdatas.resize(ZQDBGetAllCalculator(h, &hdatas[0], hdatas.size()));
		}
	}
	~AllCalculator()
	{
		std::vector<HZQDB>& hdatas = *this;
		for (auto h : hdatas) {
			ZQDBCloseCalculator(h);
		}
	}
};

class AllStrategy : public std::vector<HZQDB> {
public:
	AllStrategy() {
		std::vector<HZQDB>& hdatas = *this;
		auto count = ZQDBGetAllStrategyCount();
		if (count > 0) {
			hdatas.resize(count);
			hdatas.resize(ZQDBGetAllStrategy(&hdatas[0], hdatas.size()));
		}
	}
	~AllStrategy()
	{
		std::vector<HZQDB>& hdatas = *this;
		for (auto h : hdatas) {
			ZQDBCloseCalculator(h);
		}
	}
};

class Func
{
protected:
	HZQDB h_ = nullptr;
	bool auto_close_ = true;
public:
	Func() {}
	Func(const char* name, CALC_TYPE type, CALC_LANG_TYPE lang, const char* xml, size_t xmlflag
		, void* userdata, ZQDB_CALC_INIT_FN init_cb, ZQDB_CALC_TERM_FN term_cb
		, ZQDB_CALC_TIMER_FN timer_cb, ZQDB_CALC_HANDLE_FN handle_cb) :h_(ZQDBCreateCalcFunc(name, type, lang, xml, xmlflag, userdata, init_cb, term_cb, timer_cb, handle_cb))
	{

	}
	Func(const char* name) :h_(ZQDBOpenCalcFunc(name))
	{

	}
	Func(const char* name, CALC_TYPE type) :h_(ZQDBOpenCalcFuncEx(name, type))
	{

	}
	Func(HZQDB h, bool ref = false) :h_(h), auto_close_(ref) {
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	Func(const Func& o) 
	{
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	Func& operator=(const Func& o) {
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
		return *this;
	}
	Func(Func&& o)
	{
		h_ = o.h_;
		o.h_ = nullptr;
		auto_close_ = o.auto_close_;
		o.auto_close_ = false;
	}
	Func& operator=(Func&& o) 
	{
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_;
		o.h_ = nullptr;
		auto_close_ = o.auto_close_;
		o.auto_close_ = false;
		return *this;
	}
	~Func()
	{
		Close();
	}

	inline void Close() {
		if (h_ && auto_close_) {
			ZQDBCloseCalcFunc(h_);
			h_ = nullptr;
		}
	}
	inline bool IsOpen() { return h_ != nullptr; }
	inline operator HZQDB() const { return h_; }

	const char* GetCalcName() { return ZQDBGetCalcName(h_); }
	CALC_TYPE GetCalcType() { return ZQDBGetCalcType(h_); }
	CALC_LANG_TYPE GetCalcLang() { return ZQDBGetCalcLang(h_); }
	CALC_TARGET_TYPE GetCalcTarget() { return ZQDBGetCalcTarget(h_); }

	bool IsAuth() { return ZQDBIsCalcAuth(h_); }
	bool IsAuthorized() { return ZQDBIsCalcAuthorized(h_); }

	ssize_t HasAttr(const char* field) { return ZQDBHasCalcAttr(h_, field); }
	ssize_t GetAttrAsInt(const char* field, ssize_t def = 0) { return ZQDBGetCalcAttrAsInt(h_, field, def); }
	double GetAttrAsDouble(const char* field, double def = 0.) { return ZQDBGetCalcAttrAsDouble(h_, field, def); }
	char* GetAttrAsStr(const char* field, char* val, size_t valen) { return ZQDBGetCalcAttrAsStr(h_, field, val, valen); }
	char* GetAttrAsStrEx(const char* field, char* val, size_t valen) { return ZQDBGetCalcAttrAsStrEx(h_, field, val, valen); }

	size_t GetInputAttrCount(CALC_INPUT_FIELD_TYPE type = CALC_INPUT_FIELD_VISIBLE) { return ZQDBGetCalcInputAttrCount(h_, type); }
	//MDB_STATUS GetInputAttr(size_t pos, MDB_FIELD* field) { return ZQDBGetCalcInputAttr(h_, pos, field); }
	ssize_t GetInputAttrAsInt(const char* field, ssize_t def = 0) { return ZQDBGetCalcInputAttrAsInt(h_, field, def); }
	double GetInputAttrAsDouble(const char* field, double def = 0.) { return ZQDBGetCalcInputAttrAsDouble(h_, field, def); }
	char* GetInputAttrAsStr(const char* field, char* val, size_t valen) { return ZQDBGetCalcInputAttrAsStr(h_, field, val, valen); }
	const char* GetInputAttrName(size_t index) { return ZQDBGetCalcInputAttrNameEx(h_, index); }
	const char* GetInputAttrValue(size_t index) { return ZQDBGetCalcInputAttrValueEx(h_, index); }
	ssize_t GetInputAttrAsInt(size_t index, ssize_t def = 0) { return ZQDBGetCalcInputAttrAsIntEx(h_, index, def); }
	double GetInputAttrAsDouble(size_t index, double def = 0.) { return ZQDBGetCalcInputAttrAsDoubleEx(h_, index, def); }
	char* GetInputAttrAsStr(size_t index, char* val, size_t valen) { return ZQDBGetCalcInputAttrAsStrEx(h_, index, val, valen); }

	size_t GetReflineAttrCount() { return ZQDBGetCalcReflineAttrCount(h_); }
	ssize_t GetReflineAttrAsInt(size_t index, const char* field, ssize_t def = 0) { return ZQDBGetCalcReflineAttrAsInt(h_, index, field, def); }
	double GetReflineAttrAsDouble(size_t index, const char* field, double def = 0.) { return ZQDBGetCalcReflineAttrAsDouble(h_, index, field, def); }
	char* GetReflineAttrAsStr(size_t index, const char* field, char* val, size_t valen) { return ZQDBGetCalcReflineAttrAsStr(h_, index, field, val, valen); }

	size_t GetResultAttrCount() { return ZQDBGetCalcResultAttrCount(h_); }
	//size_t GetResultAttrCount(size_t index) { return ZQDBGetCalcResultAttrCount(h_, index); }
	//MDB_STATUS GetResultAttr(size_t index, size_t pos, MDB_FIELD* field) { return ZQDBGetCalcResultAttr(h_, index, pos, field); }
	ssize_t GetResultAttrAsInt(size_t index, const char* field, ssize_t def = 0) { return ZQDBGetCalcResultAttrAsInt(h_, index, field, def); }
	double GetResultAttrAsDouble(size_t index, const char* field, double def = 0.) { return ZQDBGetCalcResultAttrAsDouble(h_, index, field, def); }
	char* GetResultAttrAsStr(size_t index, const char* field, char* val, size_t valen) { return ZQDBGetCalcResultAttrAsStr(h_, index, field, val, valen); }
};

class Data
{
protected:
	HZQDB h_ = nullptr;
	bool auto_close_ = true;
public:
	Data() {}
	Data(const char* code, PERIODTYPE cycle, size_t cycleex = 0, size_t flags = 0) :h_(ZQDBOpenCalcData(ZQDBGetCode(code, nullptr), cycle, cycleex, flags)) {}
	Data(const char* code, const char* exchange, PERIODTYPE cycle, size_t cycleex = 0, size_t flags = 0) :h_(ZQDBOpenCalcData(ZQDBGetCode(code, exchange), cycle, cycleex, flags)) {}
	Data(HZQDB code, PERIODTYPE cycle, size_t cycleex = 0, size_t flags = 0):h_(ZQDBOpenCalcData(code, cycle, cycleex, flags)) {}
	Data(HZQDB h, bool ref = false) :h_(h), auto_close_(ref) {
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	Data(const Data& o) {
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	Data(Data&& o) {
		h_ = o.h_; o.h_ = nullptr;
		auto_close_ = o.auto_close_; o.auto_close_ = false;
	}
	Data& operator=(const Data& o)
	{
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
		return *this;
	}
	Data& operator=(Data&& o)
	{
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_; o.h_ = nullptr;
		auto_close_ = o.auto_close_; o.auto_close_ = false;
		return *this;
	}
	~Data()
	{
		Close();
	}

	inline void Close() {
		if (h_ && auto_close_) {
			ZQDBCloseCalcData(h_);
			h_ = nullptr;
		}
	}
	inline HZQDB Open(HZQDB code, PERIODTYPE cycle, size_t cycleex = 0, size_t flags = 0) { h_ = ZQDBOpenCalcData(code, cycle, cycleex, flags);  auto_close_ = true; return h_; }
	inline bool IsOpen() { return h_ != nullptr; }
	inline operator bool() const { return h_ != nullptr; }
	inline operator HZQDB() const { return h_; }

	HZQDB GetCode() { return ZQDBGetCalcDataCode(h_); }
	PERIODTYPE GetCycle() { return ZQDBGetCalcDataCycle(h_); }
	size_t GetCycleEx() { return ZQDBGetCalcDataCycleEx(h_); }

	ssize_t GetFieldAsInt(MDB_FIELD& field, ssize_t def = 0) { return ZQDBGetCalcDataFieldAsInt(h_, field, def); }
	double GetFieldAsDouble(MDB_FIELD& field, double def = 0.) { return ZQDBGetCalcDataFieldAsDouble(h_, field, def); }
	char* GetFieldAsStr(MDB_FIELD& field, char* val, size_t vallen, const char* format = nullptr) { return ZQDBGetCalcDataFieldAsStr(h_, field, val, vallen, format); }
	
	size_t GetDataMaxCount() { return ZQDBGetCalcDataMaxCount(h_); }
	size_t GetDataCount() { return ZQDBGetCalcDataCount(h_); }
	void* GetData(MDB_FIELD& field) { return ZQDBGetCalcData(h_, &field); }
	void* GetData(MDB_FIELD& field, size_t pos) { return ZQDBGetCalcDataEx(h_, &field, pos); }
	ssize_t GetDataAsInt(MDB_FIELD& field, size_t pos, ssize_t def) { return ZQDBGetCalcDataAsInt(h_, &field, pos, def); }
	double GetDataAsDouble(MDB_FIELD& field, size_t pos, double def) { return ZQDBGetCalcDataAsDouble(h_, &field, pos, def); }
	char* GetDataAsStr(MDB_FIELD& field, size_t pos, char* val, size_t vallen, const char* format = nullptr) { return ZQDBGetCalcDataAsStr(h_, &field, pos, val, vallen, format); }

	//double* GetPrice(PRICE_TYPE type, size_t pos = 0) { return ZQDBGetCalcDataPrice(h_, type, pos); }
	
	MDB_STATUS GetDataPosByTime(uint32_t date, uint32_t time, size_t *pos) { return ZQDBGetCalcDataPosByTime(h_, date, time, pos); }
	MDB_STATUS GetDataTimeByPos(size_t pos, uint32_t *date, uint32_t *time) { return ZQDBGetCalcDataTimeByPos(h_, pos, date, time); }
};

class CalcBase
{
protected:
	HZQDB h_ = nullptr;
	bool auto_close_ = true;
public:
	CalcBase() {}
	CalcBase(const char* name, HZQDB data, PERIODTYPE cycle, size_t cycleex, HZQDB input, HZQDB user = nullptr, size_t flags = 0) :h_(ZQDBOpenCalculator(name, data, cycle, cycleex, input, user, flags)) {}
	CalcBase(const char* name, HZQDB data, HZQDB input, HZQDB user = nullptr, size_t flags = 0) :CalcBase(name, data, CYC_MAX, 0, input, user) {}
	CalcBase(const char* name, CALC_TYPE type, HZQDB data, PERIODTYPE cycle, size_t cycleex, HZQDB input, HZQDB user = nullptr, size_t flags = 0) :h_(ZQDBOpenCalculatorEx(name, type, data, cycle, cycleex, input, user, flags)) {}
	CalcBase(const char* name, CALC_TYPE type, HZQDB data, HZQDB input, HZQDB user = nullptr, size_t flags = 0) :CalcBase(name, type, data, CYC_MAX, 0, input, user, flags) {}
	CalcBase(HZQDB h, bool ref = false) :h_(h), auto_close_(ref) {
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	CalcBase(const CalcBase& o) {
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
	}
	CalcBase(CalcBase&& o) {
		h_ = o.h_; o.h_ = nullptr;
		auto_close_ = o.auto_close_; o.auto_close_ = false;
	}
	CalcBase& operator=(const CalcBase& o)
	{
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_;
		auto_close_ = o.auto_close_;
		if (h_ && auto_close_) {
			ZQDBCalcRef(h_);
		}
		return *this;
	}
	CalcBase& operator=(CalcBase&& o)
	{
		if (this == &o) {
			return *this;
		}
		Close();
		h_ = o.h_; o.h_ = nullptr;
		auto_close_ = o.auto_close_; o.auto_close_ = false;
		return *this;
	}
	~CalcBase()
	{
		Close();
	}

	inline void Close() {
		if (h_ && auto_close_) {
			ZQDBCloseCalculator(h_);
			h_ = nullptr;
		}
	}
	inline HZQDB Open(const char* name, HZQDB data, PERIODTYPE cycle, size_t cycleex, HZQDB input, HZQDB user = nullptr, size_t flags = 0) { h_ = ZQDBOpenCalculator(name, data, cycle, cycleex, input, user, flags); auto_close_ = true; return h_; }
	inline HZQDB Open(const char* name, HZQDB data, HZQDB input, HZQDB user = nullptr, size_t flags = 0) { return Open(name, data, CYC_MAX, 0, input, user); }
	inline HZQDB Open(const char* name, CALC_TYPE type, HZQDB data, PERIODTYPE cycle, size_t cycleex, HZQDB input, HZQDB user = nullptr, size_t flags = 0) { h_ = ZQDBOpenCalculatorEx(name, type, data, cycle, cycleex, input, user, flags); auto_close_ = true; return h_; }
	inline HZQDB Open(const char* name, CALC_TYPE type, HZQDB data, HZQDB input, HZQDB user = nullptr, size_t flags = 0) { return Open(name, type, data, CYC_MAX, 0, input, user, flags); }
	inline bool IsOpen() { return h_ != nullptr; }
	inline operator bool() const { return h_ != nullptr; }
	inline operator HZQDB() const { return h_; }

	const char* GetCalcName() { return ZQDBGetCalcName(h_); }
	CALC_TYPE GetCalcType() { return ZQDBGetCalcType(h_); }
	CALC_LANG_TYPE GetCalcLang() { return ZQDBGetCalcLang(h_); }
	CALC_TARGET_TYPE GetCalcTarget() { return ZQDBGetCalcTarget(h_); }

	bool IsAuthorized() { return ZQDBIsCalcAuthorized(h_); }

	static HZQDB CurCalc() { return ZQDBCalculator(); }
	HZQDB Data() { return ZQDBCalculatorData(h_); }

	HZQDB GetCode() { return ZQDBGetCalcCodeByPos(h_, 0); }
	PERIODTYPE GetCycle() { return ZQDBCalculatorCycle(h_); }
	size_t GetCycleEx() { return ZQDBCalculatorCycleEx(h_); }

	size_t GetCodeCount() { return ZQDBGetCalcCodeCount(h_); }
	size_t GetAllCode(HZQDB* h, size_t count) { return ZQDBGetCalcCode(h_, h, count); }
	HZQDB GetCodeByPos(size_t pos) { return ZQDBGetCalcCodeByPos(h_, pos); }

	size_t GetInputAttrCount(CALC_INPUT_FIELD_TYPE type = CALC_INPUT_FIELD_VISIBLE) { return ZQDBGetCalcInputAttrCount(h_, type); }
	ssize_t GetInputAttrAsInt(const char* field, ssize_t def = 0) { return ZQDBGetCalcInputAttrAsInt(h_, field, def); }
	double GetInputAttrAsDouble(const char* field, double def = 0.) { return ZQDBGetCalcInputAttrAsDouble(h_, field, def); }
	char* GetInputAttrAsStr(const char* field, char* val, size_t valen) { return ZQDBGetCalcInputAttrAsStr(h_, field, val, valen); }
	const char* GetInputAttrName(size_t index) { return ZQDBGetCalcInputAttrNameEx(h_, index); }
	const char* GetInputAttrValue(size_t index) { return ZQDBGetCalcInputAttrValueEx(h_, index); }
	ssize_t GetInputAttrAsInt(size_t index, ssize_t def = 0) { return ZQDBGetCalcInputAttrAsIntEx(h_, index, def); }
	double GetInputAttrAsDouble(size_t index, double def = 0.) { return ZQDBGetCalcInputAttrAsDoubleEx(h_, index, def); }
	char* GetInputAttrAsStr(size_t index, char* val, size_t valen) { return ZQDBGetCalcInputAttrAsStrEx(h_, index, val, valen); }

	void Calc() { ZQDBCalculatorCalc(h_); }

	HZQDB GetUser() { return ZQDBCalcGetUser(h_); }

	int OrderSend(HZQDB code, char direction, char offset, char type, double volume, double price, HNMSG* rsp, size_t timeout = 3000) { return ZQDBCalcOrderSend(code, direction, offset, type, volume, price, rsp, timeout); }
	int OrderCancel(HZQDB order, HNMSG* rsp = nullptr, size_t timeout = 0) { return ZQDBCalcOrderCancel(order, rsp, timeout); }
	int OrderClose(HZQDB position, char type, double volume, double price, HNMSG* rsp, size_t timeout = 3000) { return ZQDBCalcOrderClose(position, type, volume, price, rsp, timeout); }
};

class Container : public CalcBase
{
	typedef CalcBase Base;
public:
	Container() : Base() {}
	Container(const char* name, HZQDB input = nullptr) : Base(name, CALC_CONTAINER, nullptr, CYC_MAX, 0, input) {}
	Container(const char* name, CALC_TYPE type, HZQDB data, HZQDB input = nullptr) : Base(name, type, data, CYC_MAX, 0, input) {}
	Container(HZQDB h, bool ref = false) : Base(h, ref) {}

	void ClearResult() { ZQDBCalcContainerClearResult(h_); }
	void AddResult(HZQDB h, double weight = 0.0) { ZQDBCalcContainerAddResult(h_, h, weight); }
	size_t FindResult(HZQDB h) { return ZQDBCalcContainerFindResult(h_, h); }
	size_t GetResultCount() { return ZQDBCalcContainerGetResultCount(h_); }
	size_t GetResult(HZQDB* h, size_t count) { return ZQDBCalcContainerGetResult(h_, h, count); }
	HZQDB GetResultByPos(size_t pos) const { return ZQDBCalcContainerGetResultByPos(h_, pos); }

	inline size_t size() { return GetResultCount(); }
	inline HZQDB operator[](size_t pos) const
	{
		return GetResultByPos(pos);
	}
};

class StdContainer : public Container
{
	typedef Container Base;
public:
	StdContainer(HZQDB h = nullptr) :Base("StdContainer")
	{ 
		if (h) {
			AddResult(h);
		}
	}
	StdContainer(HZQDB* h, size_t count) :Base("StdContainer") {
		for (size_t i = 0; i < count; i++)
		{
			AddResult(h[i]);
		}
	}
};

class Filter : public CalcBase
{
	typedef CalcBase Base;
public:
	//using Base::Base;
	Filter() : Base() {}
	Filter(const char* name, HZQDB input = nullptr) : Base(name, CALC_FILTER, nullptr, CYC_MAX, 0, input) {}
	Filter(HZQDB h, bool ref = false) : Base(h, ref) {}

	inline int Calc(HZQDB code) { return ZQDBCalcFilterCalc(h_, code); }
};

class Sort : public CalcBase
{
	typedef CalcBase Base;
public:
	//using Base::Base;
	Sort() : Base() {}
	Sort(const char* name, HZQDB input = nullptr) : Base(name, CALC_SORT, nullptr, CYC_MAX, 0, input) {}
	Sort(HZQDB h, bool ref = false) : Base(h, ref) {}

	bool IsDynamic() { return ZQDBCalcSortIsDynamic(h_); }

	bool Calc(HZQDB x, HZQDB y) const { return ZQDBCalcCmp(h_, x, y); }
	void Calc(HZQDB* h, size_t count) const { ZQDBCalcSort(h_, h, count); }
};

class Indicator : public CalcBase
{
	typedef CalcBase Base;
public:
	using Base::Base;

	void SetCalcData(HZQDB h, PERIODTYPE cycle, size_t cycleex) { ZQDBSetCalcData(h_, h, cycle, cycleex); }
	HZQDB GetCode() { return ZQDBGetCalcDataCode(h_); }
	PERIODTYPE GetCycle() { return ZQDBGetCalcDataCycle(h_); }
	size_t GetCycleEx() { return ZQDBGetCalcDataCycleEx(h_); }

	ssize_t GetFieldAsInt(MDB_FIELD& field, ssize_t def = 0) { return ZQDBGetCalcDataFieldAsInt(h_, field, def); }
	double GetFieldAsDouble(MDB_FIELD& field, double def = 0.) { return ZQDBGetCalcDataFieldAsDouble(h_, field, def); }
	char* GetFieldAsStr(MDB_FIELD& field, char* val, size_t vallen, const char* format = nullptr) { return ZQDBGetCalcDataFieldAsStr(h_, field, val, vallen, format); }
	
	size_t GetDataMaxCount() { return ZQDBGetCalcDataMaxCount(h_); }
	size_t GetDataCount() { return ZQDBGetCalcDataCount(h_); }
	void* GetData(MDB_FIELD& field) { return ZQDBGetCalcData(h_, &field); }
	void* GetData(MDB_FIELD& field, size_t pos) { return ZQDBGetCalcDataEx(h_, &field, pos); }
	ssize_t GetDataAsInt(MDB_FIELD& field, size_t pos, ssize_t def) { return ZQDBGetCalcDataAsInt(h_, &field, pos, def); }
	double GetDataAsDouble(MDB_FIELD& field, size_t pos, double def) { return ZQDBGetCalcDataAsDouble(h_, &field, pos, def); }
	char* GetDataAsStr(MDB_FIELD& field, size_t pos, char* val, size_t vallen, const char* format = nullptr) { return ZQDBGetCalcDataAsStr(h_, &field, pos, val, vallen, format); }

	//double* GetDataPrice(PRICE_TYPE type, size_t pos = 0) { return ZQDBGetCalcDataPrice(h_, type, pos); }
	
	MDB_STATUS GetDataPosByTime(uint32_t date, uint32_t time, size_t *pos) { return ZQDBGetCalcDataPosByTime(h_, date, time, pos); }
	MDB_STATUS GetDataTimeByPos(size_t pos, uint32_t *date, uint32_t *time) { return ZQDBGetCalcDataTimeByPos(h_, pos, date, time); }

	size_t GetReflineAttrCount() { return ZQDBGetCalcReflineAttrCount(h_); }
	ssize_t GetReflineAttrAsInt(size_t index, const char* field, ssize_t def = 0) { return ZQDBGetCalcReflineAttrAsInt(h_, index, field, def); }
	double GetReflineAttrAsDouble(size_t index, const char* field, double def = 0.) { return ZQDBGetCalcReflineAttrAsDouble(h_, index, field, def); }
	char* GetReflineAttrAsStr(size_t index, const char* field, char* val, size_t valen) { return ZQDBGetCalcReflineAttrAsStr(h_, index, field, val, valen); }

	size_t GetResultAttrCount() { return ZQDBGetCalcResultAttrCount(h_); }
	//size_t GetResultAttrCount(size_t index) { return ZQDBGetCalcResultAttrCount(h_, index); }
	ssize_t GetResultAttrAsInt(size_t index, const char* field, ssize_t def = 0) { return ZQDBGetCalcResultAttrAsInt(h_, index, field, def); }
	double GetResultAttrAsDouble(size_t index, const char* field, double def = 0.) { return ZQDBGetCalcResultAttrAsDouble(h_, index, field, def); }
	char* GetResultAttrAsStr(size_t index, const char* field, char* val, size_t valen) { return ZQDBGetCalcResultAttrAsStr(h_, index, field, val, valen); }
	
	void SetResultValueRef(size_t index, HZQDB ref_indicator, size_t ref_index) { ZQDBSetCalcResultValueRef(h_, index, ref_indicator, ref_index); }

	size_t GetResultValueMaxCount() { return ZQDBGetCalcResultValueMaxCount(h_); }
	size_t GetResultValueCount() { return ZQDBGetCalcResultValueCount(h_); }
	void* GetResultValue(size_t index, MDB_FIELD* field = nullptr) { return ZQDBGetCalcResultValue(h_, index, field); }
	void* GetResultValue(size_t index, size_t pos, MDB_FIELD* field = nullptr) { return ZQDBGetCalcResultValueEx(h_, index, pos, field); }
	ssize_t GetResultValueAsInt(size_t index, size_t pos, ssize_t def = 0) { return ZQDBGetCalcResultValueAsInt(h_, index, pos, def); }
	double GetResultValueAsDouble(size_t index, size_t pos, double def = 0.) { return ZQDBGetCalcResultValueAsDouble(h_, index, pos, def); }
	char* GetResultValueAsStr(size_t index, size_t pos, char* val, size_t vallen, const char* format = nullptr) { return ZQDBGetCalcResultValueAsStr(h_, index, pos, val, vallen, format); }
	void SetResultValueAsInt(size_t index, size_t pos, ssize_t val) { return ZQDBSetCalcResultValueAsInt(h_, index, pos, val); }
	void SetResultValueAsDouble(size_t index, size_t pos, double val) { return ZQDBSetCalcResultValueAsDouble(h_, index, pos, val); }
	void SetResultValueAsStr(size_t index, size_t pos, const char* val, size_t vallen) { return ZQDBSetCalcResultValueAsStr(h_, index, pos, val, vallen); }
};

class StrategyBase : public CalcBase
{
	typedef CalcBase Base;
public:
	using Base::Base;
};

class Script : public StrategyBase
{
	typedef StrategyBase Base;
public:
	using Base::Base;
};

class Strategy : public StrategyBase
{
	typedef StrategyBase Base;
public:
	using Base::Base;

	bool IsRun() { return ZQDBCalcStrategyIsRun(h_); }
	MDB_STATUS Start() { return ZQDBCalcStrategyStart(h_); }
	MDB_STATUS Stop() { return ZQDBCalcStrategyStop(h_); }
};

class Manager
{
protected:
public:
};

}

//统计当前位置cur的前面的num数量的数据中满足条件的数量
template<typename _Ty>
static inline size_t Count(_Ty* src, size_t count, size_t cur, size_t num, const _Ty& dst)
{
	assert(cur < count);
	if (num == 0) {
		return 0;
	}
	auto cur_num = cur + 1;
	if (cur_num < num) {
		return std::count(src, src + cur_num, dst);
	}
	else {
		return std::count(src + cur_num - num, src + cur_num, dst);
	}
}
template<typename _Ty, typename _Pr>
static inline size_t CountIf(_Ty* src, size_t count, size_t cur, size_t num, _Pr&& _Pred)
{
	assert(cur < count);
	if (num == 0) {
		return 0;
	}
	auto cur_num = cur + 1;
	if (cur_num < num) {
		return std::count_if(src, src + cur_num, _Pred);
	}
	else {
		return std::count_if(src + cur_num - num, src + cur_num, _Pred);
	}
}

//当前位置cur的前(左)num个数据的真实长度
static inline size_t RealN(size_t cur, size_t num)
{
	return cur > num ? num : cur + 1;
}

//反转当前位置
static inline size_t RvsPos(size_t count, size_t cur)
{
	assert(cur < count);
	return count - (cur + 1);
}

//pos是相对于当前位置的向前(左)偏移
static inline bool RefPosValid(size_t count, size_t cur, size_t num)
{
	return cur < count && num <= cur;
}
static inline size_t RefPos(size_t count, size_t cur, size_t num)
{
	assert(RefPosValid(count, cur, num));
	return cur - num;
}

//pos是相对于当前位置的向后(右)偏移
static inline bool RefXPosValid(size_t count, size_t cur, size_t num)
{
	return (cur < count) && ((cur + num) < count);
}
static inline size_t RefXPos(size_t count, size_t cur, size_t num)
{
	assert(RefXPosValid(count, cur, num));
	return cur + num;
}

//pos是相对于当前位置的向前(左)偏移
template<typename _Ty>
static inline _Ty& RefValue(_Ty* val, size_t count, size_t cur, size_t num)
{
	return val[RefPos(count, cur, num)];
}

//pos是相对于当前位置的向后(右)偏移
template<typename _Ty>
static inline _Ty& RefXValue(_Ty* val, size_t count, size_t cur, size_t num)
{
	return val[RefXPos(count, cur, num)];
}

//是否穿越，0表示src没有穿越dst，大于0表示src上穿dst（金叉），小于0表示src下穿dst（死叉）
template<typename _Ty>
static inline int CrossBuffer(_Ty src, _Ty dst, int src_pos, int dst_pos)
{
	if (src_pos >= 0 && dst_pos >= 0) {
		if (src[src_pos] == dst[dst_pos]) {
			return 0;
		}
		int src_i = src_pos - 1, dst_i = dst_pos - 1;
		int src_e_i = -1, dst_e_i = -1;
		while (src_i >= 0 && dst_i >= 0)
		{
			if (src[src_pos] < dst[dst_pos]) {
				if (src_e_i == -1) {
					if (src[src_i] > dst[dst_i]) {
						return -1;
					}
					else if (src[src_i] < dst[dst_i]) {
						
					}
					else {
						src_e_i = src_i;
					}
				} else {
					if (src[src_i] > dst[dst_i]) {
						return -1;
					}
					else if (src[src_i] < dst[dst_i]) {
						return 0;
					}
				}
			}
			else if (src[src_pos] > dst[dst_pos]) {
				if (src_e_i == -1) {
					if (src[src_i] > dst[dst_i]) {
						
					}
					else if (src[src_i] < dst[dst_i]) {
						return 1;
					}
					else {
						src_e_i = src_i;
					}
				}
				else {
					if (src[src_i] > dst[dst_i]) {
						return 0;
					}
					else if (src[src_i] < dst[dst_i]) {
						return 1;
					}
				}
			}
			--src_i; --dst_i;
		}
	}
	return 0;
}

template<typename _Ty>
static inline double MaxBuffer(_Ty buffer, size_t count, size_t pos, size_t num)
{
	double dvalue = 0.;
	if (buffer) {
		size_t i, j;
		i = pos;
		j = std::min<>(count, pos + num);
		if (i < j) {
			dvalue = buffer[i];
			i++;
			for (; i<j; i++)
			{
				double dtemp = buffer[i];
				if (dtemp>dvalue) {
					dvalue = dtemp;
				}
			}
		}
		else {
			assert(0);
		}
	}
	return dvalue;
}
template<typename _Ty>
static inline double MinBuffer(_Ty buffer, size_t count, size_t pos, size_t num)
{
	double dvalue = 0.;
	if (buffer) {
		size_t i, j;
		i = pos;
		j = std::min<>(count, pos + num);
		if (i < j) {
			dvalue = buffer[i];
			i++;
			for (; i<j; i++)
			{
				double dtemp = buffer[i];
				if (dtemp<dvalue) {
					dvalue = dtemp;
				}
			}
		}
		else {
			assert(0);
		}
	}
	return dvalue;
}
template<typename _Ty>
static inline double SumBuffer(_Ty buffer, size_t count, size_t pos, size_t num)
{
	double dvalue = 0.;
	if (buffer) {
		size_t i, j;
		i = pos;
		j = std::min<>(count, pos + num);
		for (; i<j; i++)
		{
			double dtemp = buffer[i];
			dvalue += dtemp;
		}
	}
	return dvalue;
}

template<typename T, CALC_TYPE type, class TBase = Calc::CalcBase>
class CCalcBase : public TBase
{
	typedef TBase Base;
public:
	static void Register(const char* name, const char* xml, size_t xmlflag)
	{
		//T* pT = static_cast<T*>(this);
		ZQDBCreateCalcFunc(name, type, CALC_LANG_C_CPP
			, xml, xmlflag, nullptr
			, [](HZQDB h, void* userdata) {
			//auto pT = (T*)userdata;
			T* p = new T(h, userdata);
			assert(p == (T*)ZQDBGetCalculatorData(h));
		}, [](HZQDB h, void* userdata) {
			assert(h->type == ZQDB_HANDLE_TYPE_CALCULATOR);
			T* p = (T*)ZQDBGetCalculatorData(h);
			assert(p);
			if (p) {
				delete p;
			}
		}, [](HZQDB h, void* userdata) {
			assert(h->type == ZQDB_HANDLE_TYPE_CALCULATOR);
			T* p = (T*)ZQDBGetCalculatorData(h);
			assert(p);
			if (p) {
				p->OnTimer();
			}
		}, [](HZQDB h, HZQDB data, ZQDB_NOTIFY_TYPE type, void* param, void* userdata) {
			T* p = (T*)ZQDBGetCalculatorData(h);
			assert(p);
			if (p) {
				p->OnCalc(data, type, param);
			}
		});
	}

public:
	CCalcBase(HZQDB h, void* userdata) :Base(h)
	{
		T* pT = static_cast<T*>(this);
		ZQDBSetCalculatorData(h, pT);
	}

	void OnTimer()
	{
	}

	void OnCalc(HZQDB data, ZQDB_NOTIFY_TYPE type, void* param)
	{
	}
};

}

#endif//

#endif//_H_ZQDB_CALC_H_